﻿using FlyRemote.Base;
using System;
using System.Collections.Generic;

namespace FlyRemote.Remote
{
    public delegate bool VirtualPageEnumProc(UInt64 BaseAddress, uint regionSize);
    /// <summary>
    /// An interface for querying virtual memory.
    /// </summary>
    public interface IMemoryAssist : IProcessObserver
    {

        string Description();


        #region 内存查询 

        /// <summary>
        /// 根据提供的参数获取在远程进程中分配的内存区域。
        /// Gets regions of memory allocated in the remote process based on provided parameters.
        /// </summary>
        /// <param name="requiredProtection">Protection flags required to be present.</param>
        /// <param name="excludedProtection">Protection flags that must not be present.</param>
        /// <param name="allowedTypes">Memory types that can be present.</param>
        /// <param name="startAddress">The start address of the query range.</param>
        /// <param name="endAddress">The end address of the query range.</param>
        /// <returns>A collection of pointers to virtual pages in the target process.</returns>
        IList<NormalizedRegion> GetVirtualPages(
            MemoryProtectionEnum requiredProtection,
            MemoryProtectionEnum excludedProtection,
            MemoryTypeEnum allowedTypes,
            UInt64 startAddress,
            UInt64 endAddress);


        /// <summary>
        /// 一个更灵活的 查询内存段的方式, 避免创建类型, 也避免多次遍历  
        /// </summary>
        void EnumVirtualPages(
            MemoryProtectionEnum requiredProtection,
            MemoryProtectionEnum excludedProtection,
            MemoryTypeEnum allowedTypes,
            UInt64 startAddress,
            UInt64 endAddress,
            VirtualPageEnumProc proc
            );



        /// <summary>
        /// 获取所有虚拟内存
        /// Gets all virtual pages in the opened process.
        /// </summary>
        /// <returns>A collection of regions in the process.</returns>
        IEnumerable<NormalizedRegion> GetAllVirtualPages();

        /// <summary>
        /// 获取目标进程中可能的最大地址。
        /// Gets the maximum address possible in the target process.
        /// </summary>
        UInt64 GetMaximumAddress();

        /// <summary>
        /// 获取目标进程中可能的最大用户模式地址。
        /// Gets the maximum usermode address possible in the target process.
        /// </summary>
        UInt64 GetMinUsermodeAddress();

        /// <summary>
        /// 获取目标进程中可能的最大用户模式地址。
        /// Gets the maximum usermode address possible in the target process.
        /// </summary>
        UInt64 GetMaxUsermodeAddress();

        /// <summary>
        /// 获取已打开进程中的所有模块。
        /// </summary>
        IEnumerable<NormalizedModule> GetModules();

        /// <summary>
        /// 获取已打开进程中所有栈的地址。
        /// Gets the address of the stacks in the opened process.
        /// </summary>
        IEnumerable<NormalizedRegion> GetStackAddresses();

        /// <summary>
        /// 获取打开的进程中所有堆的地址。
        /// Gets the addresses of the heaps in the opened process.
        /// </summary>
        IEnumerable<NormalizedRegion> GetHeapAddresses();

        /// <summary>
        /// 将地址转换为模块和地址偏移量。
        /// Converts an address to a module and an address offset.
        /// </summary>
        /// <param name="moduleName">The module name containing this address, if there is one. Otherwise, empty string.</param>
        UInt64 AddressToModule(UInt64 address, out String moduleName);

        /// <summary>
        /// 确定给定模块名的模块的基址。
        /// Determines the base address of a module given a module name.
        /// </summary>
        /// <param name="identifier">The module identifier, or name.</param>
        UInt64 ResolveModule(String identifier);

        #endregion


        #region 内存分配

        /// <summary>
        /// Allocates memory in the opened process.
        /// </summary>
        /// <param name="size">The size of the memory allocation.</param>
        /// <returns>A pointer to the location of the allocated memory.</returns>
        UInt64 AllocateMemory(Int32 size);

        /// <summary>
        /// Allocates memory in the opened process.
        /// </summary>
        /// <param name="size">The size of the memory allocation.</param>
        /// <param name="allocAddress">The rough address of where the allocation should take place.</param>
        /// <returns>A pointer to the location of the allocated memory.</returns>
        UInt64 AllocateMemory(Int32 size, UInt64 allocAddress);

        /// <summary>
        /// Deallocates memory in the opened process.
        /// </summary>
        /// <param name="address">The address to perform the region wide deallocation.</param>
        void FreeMemory(UInt64 address);

        #endregion


        #region 内存读写

        /// <summary>
        /// Reads a value from the opened processes memory.
        /// </summary>
        /// <param name="elementType">The data type to read.</param>
        /// <param name="address">The address to read from.</param>
        /// <param name="success">Whether or not the read succeeded.</param>
        /// <returns>The value read from memory.</returns>
        Object Read(DataType elementType, UInt64 address, out Boolean success);

        /// <summary>
        /// Reads a value from the opened processes memory.
        /// </summary>
        /// <typeparam name="T">The data type to read.</typeparam>
        /// <param name="address">The address to read from.</param>
        /// <param name="success">Whether or not the read succeeded.</param>
        /// <returns>The value read from memory.</returns>
        T Read<T>(UInt64 address, out Boolean success);

        /// <summary>
        /// Reads an array of bytes from the opened processes memory.
        /// </summary>
        /// <param name="address">The address to read from.</param>
        /// <param name="count">The number of bytes to read.</param>
        /// <param name="success">Whether or not the read succeeded.</param>
        /// <returns>The array of bytes read from memory, if the read succeeded.</returns>
        Byte[] ReadBytes(UInt64 address, int count, out Boolean success);


        bool ReadBytes(UInt64 address, byte[] array, int count);


        /// <summary>
        /// 评估指针
        /// </summary>
        /// <param name="address"></param>
        /// <param name="offsets"></param>
        /// <returns></returns>
        UInt64 EvaluatePointer(UInt64 address, IEnumerable<Int32> offsets);





        /// <summary>
        /// Writes a value to memory in the opened process.
        /// </summary>
        /// <param name="elementType">The data type to write.</param>
        /// <param name="address">The address to write to.</param>
        /// <param name="value">The value to write.</param>
        void Write(DataType elementType, UInt64 address, Object value);

        /// <summary>
        /// Writes a value to memory in the opened process.
        /// </summary>
        /// <typeparam name="T">The data type to write.</typeparam>
        /// <param name="address">The address to write to.</param>
        /// <param name="value">The value to write.</param>
        void Write<T>(UInt64 address, T value);

        /// <summary>
        /// Writes a value to memory in the opened process.
        /// </summary>
        /// <param name="address">The address to write to.</param>
        /// <param name="values">The value to write.</param>
        bool WriteBytes(UInt64 address, Byte[] values);


        #endregion


    }
}
